home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Database / GroupControlObject.h < prev    next >
Encoding:
Text File  |  1996-04-25  |  6.2 KB  |  183 lines  |  [TEXT/CWIE]

  1. //================================================================================
  2. // Greg Anderson
  3. // db+
  4. //
  5. // Group control object
  6. // 16 May 1994
  7. //================================================================================
  8. #pragma once
  9.  
  10. #ifndef __GROUPCONTROLOBJECT__
  11. #define __GROUPCONTROLOBJECT__
  12.  
  13. #include "Int64.h"
  14.  
  15. //
  16. // For TConstDataReference
  17. //
  18. #include "AbstractData.h"
  19.  
  20. //
  21. // For REQUIREVALIDPOINTER
  22. //
  23. #include "Debug.h"
  24.  
  25. //
  26. // Still needed?
  27. //
  28. #include "Exceptions.h"
  29.  
  30. //
  31. // 64 records per group * 32 bytes per record
  32. // produces groups that are 4K 
  33. //
  34. enum
  35. {
  36.     kLongWordsPerRecord = 8,                            // 8*4 == 32 bytes
  37.     kSingleRecordSize = (kLongWordsPerRecord * sizeof(long)),
  38.     kRecordsPerGroup = 64,                                // 32 * 64 == 4K
  39.     kLongWordsPerRecordShift = 3                        // For multiplying by kLongWordsPerRecord
  40. };
  41.  
  42. //
  43. // The only thing that the group control object knows
  44. // about the contents of a record is how to make a free
  45. // list.
  46. //
  47. enum
  48. {
  49.     kRecordIDFlagsWord                    = 0,                // Flags stored in longword 0
  50.     kFreeNodeIDByte                        = 0,                // Free node id stored in flags longword
  51.     kFreeNodeLinkByte                    = 1,                // Free node link stored longword 1
  52.     kPreviousFreeNodeLinkByte            = 2,                // Only free data records are doubly-linked
  53.     kFreeRecordIDBits                    = 0x3F000000,        // If all of these bits are set, record is free
  54.     kFreeDBRecordID                        = 0xFF000000,        // Initial value for a free DB Record
  55.     kFreeDataRecordID                    = 0x3F000000,        // Initial value for a free data record
  56.     kDataRecordIndicatorBits            = 0xC0000000,        // If these bits are clear, record is a data record
  57.     kDataRecordPhysicalSizeBits            = 0x00FF0000,        // Encoded size of a data record stored in these bits
  58.     kDataRecordPhysicalSizeShift        = 16,
  59.     kPreviousRecordPhysicalSizeBits        = 0x0000FF00,        // Encoded size of the previous data record
  60.     kPreviousRecordPhysicalSizeShift    = 8,
  61.     kFreeRecordNotLinkedToTree            = -2
  62. };
  63.  
  64. class TDatabaseDocument;
  65. class TAbstractRecord;
  66. class TAbstractBackingStore;
  67.  
  68. //
  69. // We can identify the group type by
  70. // looking at the first longword in
  71. // the group data; this will be the
  72. // ID longword of the record or data block.
  73. //
  74. // The first two bits of this longword
  75. // will be zero for data blocks, and
  76. // nonzero for record blocks.
  77. //
  78. enum GroupType
  79. {
  80.     kInvalidGroup,
  81.     kRecordGroup,
  82.     kDataBlockGroup
  83. };
  84.  
  85. //================================================================================
  86. // Class TGroupControlObject
  87. //================================================================================
  88. class TGroupControlObject
  89. {
  90.     //
  91.     // ----- Fields --------------------------------------------------------------
  92.     //
  93.     
  94. private:
  95.     long*                            fRecordData;
  96.     TDatabaseDocument*                fDocument;
  97.     long                            fFirstRecord;
  98.     Boolean                            fRecordGroupHasChanged;
  99.     TAbstractRecord*                fRecordCursors[kRecordsPerGroup];
  100.     
  101.     //
  102.     // ----- Methods -------------------------------------------------------------
  103.     //
  104.  
  105. public:
  106.                                     TGroupControlObject(TDatabaseDocument* doc, long firstRecord) :
  107.                                         fRecordData(nil),
  108.                                         fDocument(doc),
  109.                                         fFirstRecord(firstRecord),
  110.                                         fRecordGroupHasChanged(false) { REQUIREVALIDPOINTER(doc); this->InitializeRecordCursors(); };
  111.                                     ~TGroupControlObject();
  112.     void                            InitializeRecordCursors();
  113.     
  114.     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  115.     // Public interface:
  116.     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  117.  
  118. public:
  119.     Int64                            DocumentKeySpace();
  120.     
  121.     void                            CacheCreatedCursor(long recordIndex, TAbstractRecord* cursor);
  122.     void                            NotifyCursorReleased(const TAbstractRecord* cursor);
  123.     
  124.     long                            LongwordsInRecord(long recordIndex) const;
  125.     long                            BlockEncodedPhysicalSize(long recordIndex) const;
  126.     void                            SetBlockEncodedPhysicalSize(long recordIndex, long newEncodedSize);
  127.     long                            BlockPhysicalSize(long recordIndex) const { return this->LongwordsInRecord(recordIndex) * sizeof(long); }
  128.     
  129.     TAbstractRecord*                GetRecord(long recordIndex);
  130.     
  131.     long                            GetRecordWord(long recordIndex, long longwordNumber) const;
  132.     long*                            MakeRecordDataCopy(long recordIndex);
  133.     void                            ChangeRecordData(long recordIndex, long* newData, Boolean inhibitCompare = false);
  134.     const TConstDataReference        RecordDataReference(long recordIndex, long dataType, long longwordNumber, long numberOfBytes) const;
  135.  
  136.     void                            RecordGroupHasChanged() { fRecordGroupHasChanged = true; }
  137.     Boolean                            RecordGroupNeedsSave() const { return fRecordGroupHasChanged; }
  138.     
  139.     void                            PurgeIfUnreferenced();
  140.     long                            InitializeNewGroup(long nextFreeNode, long& oneFreeIndex);
  141.     long                            InitializeNewDataGroup(long desiredEncodedPhysicalSize, long& leftOverBlock);
  142.     Boolean                            IndexIsFree(long recordIndex) const;
  143.  
  144.     long                            NextFreeIndex(long afterWhichIndex) const;
  145.     long                            PreviousFreeIndex(long beforeWhichIndex) const;
  146.     void                            RecordCursorStale(long recordToFree);
  147.  
  148.     long                            TrimBlock(long blockToSplit, long newEncodedPhysicalSize);
  149.     
  150.     //
  151.     // Do debugging tests on the block links of an index
  152.     //
  153.     void                            Verify(long recordIndex, Boolean verifySubsequent = false);
  154.     
  155.     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  156.     // Private methods:
  157.     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  158.  
  159. protected:
  160.     long                            CalculateRelativeIndex(long recordIndex) const;
  161.     long                            NextRecordIndex(long recordIndex) const;
  162.     long                            PreviousRecordIndex(long recordIndex) const;
  163.     long                            FreeListToUse(long recordIndex) const { return this->BlockEncodedPhysicalSize(recordIndex); }
  164.     Boolean                            IndexIsFreeAndOnFreeList(long recordIndex) const;
  165.  
  166.     void                            WriteRecordWord(long recordIndex, long longwordNumber, long theData);
  167.     void                            WriteThroughToTransaction(long recordIndex, long longwordNumber, long theData, long theMask);
  168.  
  169.     void                            AllocateMemoryForRecordData();
  170.     void                            ReadRecordGroupFromDisk(TAbstractBackingStore* backingStoreToUse = nil);
  171.     void                            FlushChangesToDisk(TAbstractBackingStore* backingStoreToUse = nil);
  172.     void                            PurgeRecordGroupFromMemory();
  173.     
  174.     TDatabaseDocument*                DBDocument() const { return fDocument; };
  175.     long*                            RecordData(long recordIndex) const;
  176.     long                            FirstRecordIndex() const { return fFirstRecord; };
  177.  
  178.     long                            MergeFreeBlocks(long firstRecord, long recordToMerge);
  179.  
  180. };
  181.  
  182. #endif
  183.